<?php
/**
 * DolphinGTK - phpGtk framework
 *
 * Графический модуль
 *
 * @package    DolphinGTK
 * @author     Askarov Ruslan
 * @copyright  Askarov Ruslan (c) 2010.
 * @link       http://groups.google.com/group/dolphingtk
 * @license    http://www.opensource.org/licenses/gpl-license.php GPL
 * @version    0.1
 * @since      PHP v.: 5.2.1
 * @subpackage desktop
 * @category   module
 * @filesource
 */


class Ftpd
{
  private static $table;
  private static $mysql;
  private static $sqlite;


  ##############################################################################
  # Отработка событий                                                          #
  ##############################################################################


  /**
   * Метод для отлова клавиш мышки в таблице
   *
   * @access public
   * @param  int $button
   * @param  int $row
   * @return void
   */
  public function mouse_events( $button, $row )
  {
    if( $button == 3 ) {
      $menu = array(
        array( i18n('Delete'), array('Ftpd', 'delete', 65535, $row), false, 'delete' ),
        array( i18n('Edit'),  array('Ftpd', 'edut_user', $row), false, 'edit' )
      );
      self::$table->menu($menu);
    }
  }




  /**
   * Метод для удаления пользователя, по средству отлова клавишь клавиатуры
   *
   * @access public
   * @param  int $key - клавиша, нажатая пользователем
   * @param  int $row - ряд, с которым работает пользователь
   * @return void
   */
  public function delete( $key = false, $row = false )
  {
    if( $key == 65535 )
    {
      $conf = Win::confirm(WIN_TITLE, 'Are you sure to delete a ftp user?');

      if( $conf == true )
      {
        self::$sqlite->connect();

        $username = self::$table->get_values($row, 1);
        $username = trim($username);

        self::$sqlite->delete(
            'ftpd', array(
            'username' => $username
          )
        );

        self::$table->delete($row);

        $msg = i18n('Ftp user "%s" success removed!', $username);
        Win::alert( WIN_TITLE, $msg );

        self::delete_user($username);

        self::$sqlite->disconnect();
      }
    }
  }




  /**
   *
   * @param bool $flag
   * @param string $username
   * @param string $password
   * @param num $row_num
   * @param array $old_value
   */
  public function editable($flag, $username, $password, $row_num = false, $old_value = '')
  {
    if( !empty( $username ) ) {
      self::$sqlite->connect();
      self::$sqlite->update(
        'ftpd', array(
          'flag' => $flag
        ), array(
          'username' => $username
        )
      );
      self::$sqlite->disconnect();
      self::user_activity($flag, $username, $password);
    } elseif(empty( $username )) {
      self::$table->update($row_num, 0, false);
    } else {
      Win::alert(WIN_TITLE,'Ошибочка вышла!');
    }
  }




  /**
   * Метод для добавления пользователей
   *
   * @access public
   * @param  array $old_data
   * @return bool
   */
  public function add_user( $old_data = false )
  {
    if( !is_array($old_data) ) $old_data = array('', '');
    
    $values = Win::prompt(
      array(
        i18n('User login: ')  => $old_data[0],
        i18n('User password') => $old_data[1],
      ),
      200,
      i18n('Create profile'), 'add'
    );
    
    if( $values === false ) return false;

    if( !empty($values[0]) && !empty($values[1]) )
    {
      self::create_user(
        $values[0], $values[1]
      );

      $insert = array(
        'flag'     => true,
        'username' => $values[0],
        'password' => $values[1]
      );

      self::$sqlite->connect();
      self::$sqlite->insert(
        'ftpd', $insert
      );
      self::$sqlite->disconnect();

      self::$table->insert( 
        array_values($insert), true
      );

      Tray::notify(
        array(
          'DolphinGTK',
          vsprintf(
            'User "%s" success added', $values[0]
          )
        )
      );
    }
    elseif( !empty($values[0]) && empty($values[1]) )
    {
      Win::alert(
        WIN_TITLE,'Неверные данные',
        'dialog_error'
      );
      self::add_user( $values );
    }
  }




  /**
   *
   * @param <type> $row_id
   * @return bool
   */
  public function edut_user( $row_id )
  {
    if( is_numeric($row_id) && Win::$os == 'linux' ):
    $old_password = self::$table->get_values($row_id,2);
    $username = self::$table->get_values($row_id,1);

    $values = Win::prompt(
      array(
        i18n('User password') => $old_password
      ),
      200,
      i18n('Change pass'), 'change'
    );

    if( $values === false ) return false;

    if( !empty($values[0]) && $old_password != $values[0] )
    {
      self::$table->update($row_id, 2, $values[0]);

      self::$sqlite->connect();
      self::$sqlite->update(
        'ftpd', array(
          'password' => $values[0]
        ), array(
          'username' => $username
        )
      );
      self::$sqlite->disconnect();

      self::change_pass( $username, $values[0] );

      Tray::notify(
        array(
          'DolphinGTK',
          vsprintf(
            'User "%s" pass changed', $username
          )
        )
      );

      return true;
    }
    endif;

    return false;
  }




  /**
   * Метод для сохранения FTP конфигурации
   * 
   * @access public
   * @return void
   */
  public function preferences()
  {
    $values = Win::prompt(
      array(
        i18n('Ftp mysql host')        => Config::get('FTP_DB_HOST'),
        i18n('Ftp mysql user')        => Config::get('FTP_DB_USER'),
        i18n('Ftp mysql pass')        => Config::get('FTP_DB_PASS'),
        i18n('Ftp mysql db name')     => Config::get('FTP_DB_NAME'),
        i18n('Ftp user home path')    => Config::get('FTP_HOME_PATH'),
        i18n('Ftp backup directory')  => Config::get('FTP_BACKUP'),
        i18n('Ftp user group')        => Config::get('FTP_GROUP')
      ),
      200,
      i18n('Save'), 'save'
    );

    if( $values !== false && is_array($values) )
    {
      Config::update( 'FTP_DB_HOST',   $values[0] );
      Config::update( 'FTP_DB_USER',   $values[1] );
      Config::update( 'FTP_DB_PASS',   $values[2] );
      Config::update( 'FTP_DB_NAME',   $values[3] );
      Config::update( 'FTP_HOME_PATH', $values[4] );
      Config::update( 'FTP_BACKUP',    $values[5] );
      Config::update( 'FTP_GROUP',     $values[6] );
    }
  }


  ##############################################################################
  # Касательно передачи в основное окно                                        #
  ##############################################################################


  public function set()
  {
    /*
    // Это пример добавления ключей конфигурации.
    if( Config::get('FTP_DB_USER') === false ):
    // хост бд
    Config::set('FTP_DB_HOST', 'localhost');
    // логин пользователя базы данных vsftpd
    Config::set('FTP_DB_USER', 'ftpd');
    // пароль к бд
    Config::set('FTP_DB_PASS', 'pass');
    // имя бд
    Config::set('FTP_DB_NAME', 'ftpd');
    // путь к директориям пользователей
    Config::set('FTP_HOME_PATH', '/home/vsftpd/');
    // путь к резервной копии
    Config::set('FTP_BACKUP', '/home/vsftpd_back/');
    // группа vsftpd
    Config::set('FTP_GROUP', 'nogroup');
    print "added!\n";
    endif;
    */

    // MySQL
    self::$mysql = new Mysql(
      Config::get('FTP_DB_HOST'), Config::get('FTP_DB_USER'),
      Config::get('FTP_DB_PASS'), Config::get('FTP_DB_NAME')
    );

    // SQLite
    $db_file      = OS::get_appdata() . 'database.sqlite';
    self::$sqlite = new Sqlite($db_file);

    self::$sqlite->connect();
    self::$sqlite->query("select name from sqlite_master where name = 'ftpd';");
    if( self::$sqlite->num() == 0 ) {
      self::$sqlite->query("CREATE TABLE ftpd (flag INTEGER, username TEXT, password TEXT, id INTEGER PRIMARY KEY);");
    }

    // создали экземпляр класса, для работы с таблицами
    self::$table = new Table;

    // задали цвета
    self::$table->row_color('#dddddd', '#ffffff');

    // зарезервироли кол-во ячеек
    self::$table->reserve(50);

    // разрешим для примера сортировку по
    // первому полю. отсчет идет от 0
    self::$table->sortable(
      true, array(1)
    );

    // редактирование полей:
    // первый параметр говорит о том, что можно редактировать.
    // второй - callback функция.
    // и третий параметр, это поля для редактирования.
    self::$table->editable(
      true, array('Ftpd', 'editable'),
      array()
    );

    // создали табличку
    self::$table->create(
      array('checkbox', '#'),
      array('string', i18n('Username')),
      array('string', i18n('Password'))
    );

    // отлавливаем мышь
    self::$table->on_bottom(
      array('Ftpd','mouse_events')
    );

    // отлавливаем клавиши
    self::$table->on_key(
      array('Ftpd','delete')
    );

    $saved = self::$sqlite->select('ftpd');

    if( $saved['num'] > 0 )
    {
      if( is_array( $saved['result'] ) ):

      foreach( $saved['result'] as $row => $value )
      {
        $set[] = $value['flag'];
        $set[] = $value['username'];
        $set[] = $value['password'];
        self::$table->update($row, false, $set);
        unset($set);
      }

      endif;
    }

    self::$sqlite->disconnect();

    // создали кнопку добавление пользователя
    $button = Widgets::button(
      i18n('Add new user'), 'add',
      array('Ftpd', 'add_user')
    );

    // упаковали всё
    $box = new GtkVBox();
    $box->pack_start(self::$table->get(200), 0, 0);
    $box->pack_start($button, 0, 0);

    // отдали в главное окно
    return $box;
  }




  ##############################################################################
  # Все что ниже, касается уже особенности ОС Linux. Если вам этот модуль так  #
  # же интересен, и вы хотите партировать это на Win или Mac, поправьте код    #
  # под особенности вашей ОС                                                   #
  ##############################################################################




  /**
   * Метод добавляет нового пользователя и создает рабочую директорию
   *
   * @access private
   * @param  string $username
   * @param  string $password
   * @return bool
   */
  private function create_user( $username, $password )
  {
    if( Win::$os == 'linux' ):
    if( !empty($username) && !empty($password) ):
    self::$mysql->connect();
    $check = self::$mysql->select(
        'accounts', array(
        'username' => $username
      )
    );

    if( $check['num'] == 0 )
    {
      self::$mysql->query("
        INSERT INTO `accounts` (`username`, `pass`)
        VALUES ('$username', PASSWORD('$password'));
      ");

      $directory = Config::get('FTP_HOME_PATH').$username;
      $ftp_user  = Config::get('FTP_DB_USER');
      $ftp_group = Config::get('FTP_GROUP');

      OS::exec("mkdir $directory >& /dev/null");
      OS::exec("chown $ftp_user:$ftp_group $directory >& /dev/null");
      OS::exec("chmod 770 $directory >& /dev/null");

      return true;
    }
    self::$mysql->disconnect();
    endif;
    endif;
    
    return false;
  }




  /**
   * Метод для смены пароля пользователя
   *
   * @access private
   * @param  string $username
   * @param  string $password
   * @return bool
   */
  private function change_pass( $username, $password )
  {
    if( Win::$os == 'linux' ):
    if( !empty($username) && !empty($password) ):
    self::$mysql->connect();
    $check = self::$mysql->select(
        'accounts', array(
        'username' => $username
      )
    );

    if( $check['num'] > 0 )
    {
      self::$mysql->query("
        UPDATE `accounts` SET `pass` = PASSWORD('$password')
        WHERE `username` = '$username';
      ");
    
      return true;
    }
    self::$mysql->disconnect();
    endif;
    endif;
    return false;
  }




  /**
   * Метод удяляет пользователя, удаляет директорию, и создаёь backup
   *
   * @access private
   * @param  string $username
   * @return bool
   */
  private function delete_user( $username )
  {
    if( !empty($username) && Win::$os == 'linux'):
    self::$mysql->connect();
    $check = self::$mysql->select(
        'accounts', array(
        'username' => $username
      )
    );

    if( $check['num'] > 0 )
    {
      self::$mysql->delete(
          'accounts', array(
          'username' => $username
        )
      );

      $directory      = Config::get('FTP_HOME_PATH').$username;
      $ftp_user       = Config::get('FTP_DB_USER');
      $ftp_group      = Config::get('FTP_GROUP');
      $ftp_backup_dir = Config::get('FTP_BACKUP');
      $archive_dir    = $directory . '-' . date("d-m-Y") . '.tar.gz';

      if( !is_dir($ftp_backup_dir) ) {
        mkdir($ftp_backup_dir, 0755);
      }

      OS::exec("tar -czvf $archive_dir $directory >& /dev/null");
      OS::exec("rm -r $directory >& /dev/null");
      OS::exec("mv $archive_dir $ftp_backup_dir");

      return true;
    }
    self::$mysql->disconnect();
    endif;
    return false;
  }




  /**
   * Метод для активации и деактивации пользователя FTP.
   *
   * @access public
   * @param  bool $flag
   * @param  string $username
   * @param  string $password
   * @return void
   */
  function user_activity($flag, $username, $password)
  {
    if( Win::$os == 'linux' ):
    if( !empty($username) && !empty($password) ):
    if( $flag == false )
    {
      $str = array();
      $str = array_merge(range(0,9), range('a','z'), range('A','Z'));
      shuffle($str);
      $password = implode('',array_slice($str, 0, 25))."\n";
      self::change_pass( $username, $password );
    }
    else
    {
      self::change_pass( $username, $password );
    }
    endif;
    endif;
  }

}
?>
